//============================================================================
// Name        : xyne.cpp
// Author      : dfoelber
// Description : This main file will be just an entry point later.
//				 For now, it will contain test code from the awesome SDL
//				 tutorials at http://lazyfoo.net/SDL_tutorials/index.php
//============================================================================

//@Include: object.h
//@Include: image_manager.h
//@Include: graphics/surface.h
//@Include: graphics/screen.h
//@Include: physics/area.h
//@Include: physics/path.h
//@Include: effect/region_effect.h

// INCLUDES //
#include "SDL/SDL.h"
#include "SDL/SDL_framerate.h"
#include "graphics/screen.h"
#include "physics/boundary.h"
#include "physics/path.h"
#include "physics/puzzle_path.h"
#include "effect/effect.h"
#include "effect/slide_effect.h"
#include "image_manager.h"
#include "render_manager.h"
#include "queue_region.h"
#include "alignment_region.h"
#include "object.h"
#include "layout.h"
#include "hand_region.h"
#include "player_region.h"
#include "card/card.h"
#include "graphics/graphics.h"
#include "puzzle_region.h"
#include <string>
#include <iostream>
//////////////

using namespace std;

/// Hardcoded for now
const int SCREEN_WIDTH = 1024;
/// Hardcoded for now
const int SCREEN_HEIGHT = 768;
/// Hardcoded for now
const int SCREEN_BPP = 32;
/// Temporarily holding the Screen object
Screen* screen = NULL;
/// Max framerate
const int MAX_FRAMERATE = 30;

/// Create the test deck
vector<CardInfo*> CreateDeck()
{
	vector<CardInfo*> deck;
	vector<vector<char> > cardCost;
	for( int y = 0; y < 6; y++ )
	{
		vector<char> v;
		for( int x = 0; x < 6; x++ )
			v.push_back( ' ' );
		cardCost.push_back( v );
	}
	cardCost[2][2] = 'R';
	cardCost[3][2] = 'R';
	cardCost[2][3] = 'R';
	cardCost[3][3] = 'R';
	vector<Effect*> effects;
	vector<int> damage;
	damage.push_back(5);
	DirectDamageEffect* effect = new DirectDamageEffect(damage, EFFECT_CATEGORY_INSTANT, "Damage (Small)", "");
	effects.push_back(effect);
	damage.push_back(10);
	damage.push_back(15);
	damage.push_back(20);
	effect = new DirectDamageEffect(damage, EFFECT_CATEGORY_PER_LEVEL, "Damage (Small)", "");
	effects.push_back(effect);
	deck.push_back(new CardInfo("Fireball", cardCost, effects, "Blah blah blah"));
	effects.clear();
	cardCost[3][2] = ' ';
	cardCost[2][3] = ' ';
	cardCost[3][3] = ' ';
	deck.push_back(new CardInfo("Red", cardCost, effects, "Blah blah blah"));
	deck.push_back(new CardInfo("Red", cardCost, effects, "Blah blah blah"));
	cardCost[2][2] = 'B';
	deck.push_back(new CardInfo("Blue", cardCost, effects, "Blah blah blah"));
	deck.push_back(new CardInfo("Blue", cardCost, effects, "Blah blah blah"));
	deck.push_back(new CardInfo("Blue", cardCost, effects, "Blah blah blah"));
	cardCost[2][2] = 'Y';
	deck.push_back(new CardInfo("Yellow", cardCost, effects, "Blah blah blah"));
	deck.push_back(new CardInfo("Yellow", cardCost, effects, "Blah blah blah"));
	deck.push_back(new CardInfo("Yellow", cardCost, effects, "Blah blah blah"));
	cardCost[2][2] = 'G';
	deck.push_back(new CardInfo("Green", cardCost, effects, "Blah blah blah"));
	deck.push_back(new CardInfo("Green", cardCost, effects, "Blah blah blah"));
	deck.push_back(new CardInfo("Green", cardCost, effects, "Blah blah blah"));
	cardCost[2][2] = 'W';
	deck.push_back(new CardInfo("White", cardCost, effects, "Blah blah blah"));
	deck.push_back(new CardInfo("White", cardCost, effects, "Blah blah blah"));
	deck.push_back(new CardInfo("White", cardCost, effects, "Blah blah blah"));
	cardCost[2][2] = 'L';
	deck.push_back(new CardInfo("Black", cardCost, effects, "Blah blah blah"));
	deck.push_back(new CardInfo("Black", cardCost, effects, "Blah blah blah"));
	deck.push_back(new CardInfo("Black", cardCost, effects, "Blah blah blah"));
	
	return deck;
}

/**
* Xyne's entry point. 
**/
int main( int argc, char* args[] )
{	
	/// temporary variables, move them later!
	int currentX = -1; int currentY = -1;
	Object* currentObject = NULL;
	int timeCounter = 0;
	int tooltipThreshold = 1000;
	
	screen = new Screen();
	
	if( !screen->Show( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP ) )
	{
		return 1;
	}
	
	ImageManager::GetManager()->LoadImages();
	
	// Load the background
	Layout* layout = new Layout();
	Surface* background = layout->CreateBackground();
	
	// Draw the background initially
	RenderManager::GetManager()->LoadScreen(screen);
	RenderManager::GetManager()->LoadBackground(background);
	
	bool quit = false;
	int ticks = 0;
	SDL_Event event;
	
	// Create the player region
	PlayerRegion* playerRegion = new PlayerRegion();
	SDL_Rect playerArea = layout->GetPlayerRegionArea();
	playerRegion->SetBoundary( playerArea.x, playerArea.y, playerArea.w, playerArea.h );
	playerRegion->SetPlayerName("RabydDonkey");
	playerRegion->SetTotalHealth(100);
	playerRegion->SetHealth(100);
	playerRegion->LoadCards(CreateDeck());
	
	// Create the card region (the player's hand)
	HandRegion* handRegion = new HandRegion();
	SDL_Rect handArea = layout->GetHandRegionArea();
	handRegion->SetBoundary( handArea.x, handArea.y, handArea.w, handArea.h );
	handRegion->SetPlayerRegion( playerRegion );
	handRegion->GrabCards();
	
	// Create the alignment region
	AlignmentRegion* alignmentRegion = new AlignmentRegion();
	SDL_Rect alignmentArea = layout->GetAlignmentRegionArea();
	alignmentRegion->SetBoundary( alignmentArea.x, alignmentArea.y, alignmentArea.w, alignmentArea.h );
	
	// Create the queue region
	QueueRegion* queueRegion = new QueueRegion();
	SDL_Rect queueArea = layout->GetQueueRegionArea();
	queueRegion->SetBoundary( queueArea.x, queueArea.y, queueArea.w, queueArea.h );
	queueRegion->SetAlignmentRegion(alignmentRegion);
	queueRegion->Initialize();
	
	// Create the puzzle region (the player's gem board)
	PuzzleRegion* region = new PuzzleRegion();
	SDL_Rect puzzleArea = layout->GetPuzzleRegionArea();
	region->SetBoundary( puzzleArea.x, puzzleArea.y, puzzleArea.w, puzzleArea.h );
	region->SetQueueRegion(queueRegion);
	region->Start();
	
	handRegion->SetPuzzleRegion(region);
	
	// While the user wants the game to continue
    while( !quit )
    {	
    	// hack, change later
    	//timeRegion->AddListener( &adapter );
    	
    	ticks = SDL_GetTicks();
    	
    	//While there's events to handle
    	//SDL_Event event;
    	while( SDL_PollEvent( &event ) )
        {            
            // If the user has Xed out the window
            if( event.type == SDL_QUIT )
            {
                // Quit the program
                quit = true;
            }
            else if( event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE )
        	{
            	// Quit the program
        		quit = true;
        	}
            else
            {
            	if( event.type == SDL_MOUSEMOTION ) // For tooltips
            	{
            		currentX = event.button.x;
            		currentY = event.button.y;
            		currentObject = region->GetObjectByCoordinate(currentX, currentY);
            		timeCounter = 0;
            	}
            	
                // Handle events
            	handRegion->ProcessEvent( event );
            	playerRegion->ProcessEvent( event );
            	queueRegion->ProcessEvent( event );
            	alignmentRegion->ProcessEvent( event );
        		region->ProcessEvent( event );
            }
        }
    	
    	// Render
    	region->Render();
    	playerRegion->Render();
    	handRegion->Render();
    	queueRegion->Render();
    	alignmentRegion->Render();
    	
    	if( timeCounter > tooltipThreshold )
    	{
    		// tooltip logic goes here..
    	}
    	
    	RenderManager::GetManager()->Render();
    	
        // Cap the frame rate, this will have to be done for efficiently later
        if( SDL_GetTicks() - ticks < 1000 / MAX_FRAMERATE )
        {
        	int delay = ( 1000 / MAX_FRAMERATE ) - (SDL_GetTicks() - ticks);
            SDL_Delay( delay );
        }
        
        // Let the region know that time has passed
        region->TimePassed( SDL_GetTicks() - ticks );
        playerRegion->TimePassed( SDL_GetTicks() - ticks );
        handRegion->TimePassed( SDL_GetTicks() - ticks );
        queueRegion->TimePassed( SDL_GetTicks() - ticks );
        alignmentRegion->TimePassed( SDL_GetTicks() - ticks );
        
        timeCounter += SDL_GetTicks() - ticks;
    }
    
    delete background;
    delete layout;
    
    delete region;
    delete playerRegion;
    delete queueRegion;
    delete handRegion;
    delete alignmentRegion;
    
    delete screen;
    
	return 0;
}
